aboutsummaryrefslogtreecommitdiff
path: root/src/routes/user/[user]/badges
diff options
context:
space:
mode:
authorFuwn <[email protected]>2023-10-26 15:41:57 -0700
committerFuwn <[email protected]>2023-10-26 15:41:57 -0700
commit9bac3b6b6a9103841a3456436c65af66549a83da (patch)
tree4273c0ebe5567109daf8b7a4d2c92d51694677cf /src/routes/user/[user]/badges
parentfix(feeds): html encode title (diff)
parentfeat: move back to bun (diff)
downloaddue.moe-9bac3b6b6a9103841a3456436c65af66549a83da.tar.xz
due.moe-9bac3b6b6a9103841a3456436c65af66549a83da.zip
merge: branch 'badges'
Diffstat (limited to 'src/routes/user/[user]/badges')
-rw-r--r--src/routes/user/[user]/badges/+page.server.ts11
-rw-r--r--src/routes/user/[user]/badges/+page.svelte125
2 files changed, 136 insertions, 0 deletions
diff --git a/src/routes/user/[user]/badges/+page.server.ts b/src/routes/user/[user]/badges/+page.server.ts
new file mode 100644
index 00000000..4be5bcd2
--- /dev/null
+++ b/src/routes/user/[user]/badges/+page.server.ts
@@ -0,0 +1,11 @@
+import { user } from '$lib/AniList/user.js';
+import { getUserBadges } from '$lib/userBadgesDatabase.js';
+
+export const load = async ({ params }) => {
+ const badges = getUserBadges((await user(params.user)).id);
+
+ return {
+ username: params.user,
+ badges
+ };
+};
diff --git a/src/routes/user/[user]/badges/+page.svelte b/src/routes/user/[user]/badges/+page.svelte
new file mode 100644
index 00000000..324d568e
--- /dev/null
+++ b/src/routes/user/[user]/badges/+page.svelte
@@ -0,0 +1,125 @@
+<script lang="ts">
+ import { userIdentity } from '$lib/AniList/identity.js';
+ import type { Badge } from '$lib/userBadgesDatabase.js';
+ import { onMount } from 'svelte';
+
+ export let data;
+
+ let editMode = false;
+ let currentUserIdentity: ReturnType<typeof userIdentity>;
+
+ onMount(async () => {
+ if (data.user) {
+ currentUserIdentity = userIdentity(data.user);
+ } else {
+ currentUserIdentity = new Promise((resolve) =>
+ resolve({
+ name: 'Guest',
+ id: -1
+ })
+ );
+ }
+ });
+
+ const submitBadge = () => {
+ const imageURL = document.querySelector('input[name="image_url"]') as HTMLInputElement;
+ const activityURL = document.querySelector('input[name="activity_url"]') as HTMLInputElement;
+ const description = document.querySelector('input[name="description"]') as HTMLInputElement;
+
+ fetch(
+ `/api/badges/add?image=${encodeURIComponent(imageURL.value)}&post=${encodeURIComponent(
+ activityURL.value
+ )}&description=${encodeURIComponent(description.value)}`,
+ {
+ method: 'POST'
+ }
+ ).then(() => {
+ imageURL.value = '';
+ activityURL.value = '';
+ description.value = '';
+ });
+ };
+
+ const removeBadge = (badge: Badge) => {
+ fetch(`/api/badges/remove?id=${badge.id}`, {
+ method: 'POST'
+ }).then(() => {
+ (document.querySelector(`#badge-${badge.id}`) as HTMLAnchorElement).style.display = 'none';
+ });
+ };
+</script>
+
+{#await currentUserIdentity}
+ Loading ...
+{:then identity}
+ {@const isOwner = identity && identity.name === data.username}
+ <p>
+ <a href={`/user/${data.username}`}>Back to Profile</a>
+ {#if isOwner}
+ •
+ <a href={`#`} on:click={() => (editMode = !editMode)}>
+ {editMode ? 'Disable' : 'Enable'} Edit Mode
+ </a>
+ {/if}
+ </p>
+
+ {#if editMode && isOwner}
+ <p>
+ Delete mode is enabled. Click on an image to delete it. There is no confirmation, so be
+ careful!
+ </p>
+
+ <p>
+ <input type="text" placeholder="Image URL" name="image_url" minlength="1" maxlength="1000" />
+ <input
+ type="text"
+ placeholder="Activity URL"
+ name="activity_url"
+ minlength="1"
+ maxlength="1000"
+ />
+ <input
+ type="text"
+ placeholder="Description (Optional)"
+ name="description"
+ minlength="1"
+ maxlength="1000"
+ />
+ <a href={`#`} on:click={submitBadge}>Add Badge</a>
+ </p>
+ {/if}
+
+ <div id="badges">
+ {#each data.badges as badge}
+ {#if editMode}
+ <a href={`#`} on:click={() => removeBadge(badge)} id={`badge-${badge.id}`}>
+ <img src={badge.image} alt={badge.description} />
+ </a>
+ {:else}
+ <a href={badge.post} target="_blank" id={`badge-${badge.id}`}>
+ <img src={badge.image} alt={badge.description} />
+ </a>
+ {/if}
+ {/each}
+ </div>
+{/await}
+
+<style>
+ /* body {
+ margin: 0;
+ padding: 0;
+ text-align: center;
+ background-color: #151f2e;
+ } */
+
+ img {
+ width: 100%;
+ height: auto;
+ }
+
+ #badges {
+ display: grid;
+ grid-template-columns: repeat(auto-fill, minmax(8%, 1fr));
+ grid-gap: 0;
+ }
+</style>